package com.jwdf.uda.http;

import android.content.Context;

import com.jwdf.uda.BuildConfig;
import com.jwdf.uda.R;
import com.jwdf.uda.event.LongTaskEvent;
import com.jwdf.uda.fileupload.CountingRequestBody;
import com.jwdf.uda.fileupload.interceptor.UploadProgressInterceptor;
import com.jwdf.uda.http.interceptor.FetchCookiesInterceptor;
import com.jwdf.uda.http.interceptor.SetCookiesInterceptor;
import com.jwdf.uda.utils.ConfigUtils;
import com.jwdf.uda.utils.EventBusUtil;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.protobuf.ProtoConverterFactory;

/**
 * 类说明：Retrofit初始化
 * 作者：huangqiuxin on 2016/5/11 16:23
 * 邮箱：648859026@qq.com
 */
public class ApiServiceModule {
    private static ApiServiceModule ourInstance = new ApiServiceModule();
    //URL定义
//    private String BASE_URL = "https://uda.91uda.com";
//    private String BASE_URL = "https://dev.91uda.com";
    private Retrofit mApiRetrofit = null;
    private Retrofit mApiTaskRetrofit = null;
    private Retrofit mApiFileUploadRetrofit = null;
    private Retrofit mApiWXPayRetrofit = null;
    private ApiService mApiService = null;
    private ApiService mApiTaskService = null;
    private ApiFileUploadService mApiFileUploadService = null;
    private ApiFileUploadListService mApiFileUploadListService=null;
    private ApiWXPayService mApiWXPayService = null;

    private ApiServiceModule() {
    }

    public static ApiServiceModule getInstance() {
        return ourInstance;
    }

    public ApiService providerApiService(Context context) {

        if (mApiService == null) {
            mApiService = providerApiRetrofit(context).create(ApiService.class);
        }
        return mApiService;
    }
    Retrofit providerApiRetrofit(Context context) {
        if (mApiRetrofit == null) {
            mApiRetrofit = new Retrofit.Builder().baseUrl(ConfigUtils.getApiUrl(context)).addConverterFactory(ProtoConverterFactory.create()).client(providerOkHttpClient(context)).build();
        }
        return mApiRetrofit;
    }
    OkHttpClient providerOkHttpClient(Context context) {
        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        builder.connectTimeout(20, TimeUnit.SECONDS);
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(logging);
            builder.addNetworkInterceptor(logging);
        }
        builder.addInterceptor(new FetchCookiesInterceptor(context));
        builder.addInterceptor(new SetCookiesInterceptor(context));
        try {
            builder.sslSocketFactory(getSSLSocketFactory(context));
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

        return builder.build();
    }
    private SSLSocketFactory getSSLSocketFactory(Context context) throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream inputStream = context.getResources().openRawResource(R.raw.uda_91uda);
        Certificate ca = cf.generateCertificate(inputStream);
        inputStream.close();

        KeyStore keyStore = KeyStore.getInstance("bks");
        keyStore.load(null, null);
        keyStore.setCertificateEntry("uda", ca);
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, wrappedTrustManagers, null);
        return sslContext.getSocketFactory();
    }
    private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
        final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
        return new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                try {
                    originalTrustManager.checkClientTrusted(chain, authType);
                } catch(CertificateException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                try {
                    originalTrustManager.checkServerTrusted(chain, authType);
                } catch(CertificateException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return originalTrustManager.getAcceptedIssuers();
            }
        }};
    }
    public ApiService providerTaskApiService(Context context, int i) {
        mApiTaskService = providerTaskApiRetrofit(context, i).create(ApiService.class);
        return mApiTaskService;
    }
    Retrofit providerTaskApiRetrofit(Context context, int i) {
            mApiTaskRetrofit = new Retrofit.Builder().baseUrl(ConfigUtils.getApiUrl(context)).addConverterFactory(ProtoConverterFactory.create()).client(providerOkHttpClient(context, i)).build();
            return mApiTaskRetrofit;
    }
    OkHttpClient providerOkHttpClient(Context context,final int i) {
        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        builder.connectTimeout(20, TimeUnit.SECONDS);
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(logging);
            builder.addNetworkInterceptor(logging);
        }
        builder.addInterceptor(new FetchCookiesInterceptor(context));
        builder.addInterceptor(new SetCookiesInterceptor(context));
        builder.addInterceptor(new UploadProgressInterceptor(new CountingRequestBody.Listener() {
            @Override
            public void onRequestProgress(long bytesWritten, long contentLength,boolean done) {
//                if(BuildConfig.DEBUG) {
                    int progress=(int) ((100 * bytesWritten) / contentLength);
                    double a=(progress*0.1+90);
//                    Log.e("eeee"+i, "progress: " + progress + "..." + a + "bytesWritten" + bytesWritten + "----contentLength" + contentLength);
                    EventBusUtil.post(new LongTaskEvent(LongTaskEvent.LONG_TASK_QUESTION_END, a, i));
//                }
            }
        }));
        try {
            builder.sslSocketFactory(getSSLSocketFactory(context));
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

        return builder.build();
    }

    public ApiFileUploadService providerApiFileUploadService(Context context) {
        if (mApiFileUploadService == null) {
            mApiFileUploadService = providerApiFileUploadRetrofit(context).create(ApiFileUploadService.class);
        }
        return mApiFileUploadService;
    }
    Retrofit providerApiFileUploadRetrofit(Context context) {
        if (mApiFileUploadRetrofit == null) {
            mApiFileUploadRetrofit = new Retrofit.Builder().baseUrl(ConfigUtils.getUploadUrl(context)).addConverterFactory(GsonConverterFactory.create()).client(providerFileUploadOkHttpClient(context)).build();
        }
        return mApiFileUploadRetrofit;
    }
    OkHttpClient providerFileUploadOkHttpClient(Context context) {
        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.readTimeout(100, TimeUnit.SECONDS);
        builder.writeTimeout(100, TimeUnit.SECONDS);
        builder.connectTimeout(100, TimeUnit.SECONDS);
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(logging);
            builder.addNetworkInterceptor(logging);
        }
        builder.addInterceptor(new FetchCookiesInterceptor(context));
        builder.addInterceptor(new SetCookiesInterceptor(context));
//        builder.addInterceptor(new UploadProgressInterceptor(new CountingRequestBody.Listener() {
//            @Override
//            public void onRequestProgress(long bytesWritten, long contentLength,boolean done) {
//                if(BuildConfig.DEBUG) {
//                    Log.e("aaa", "progress: " + (int) ((100 * bytesWritten) / contentLength) + "..." + (done ? "done" : "uploading"));
        //                    double progress=(double) ((100 * bytesWritten) / contentLength)*0.8;
//                    EventBusUtil.post(new LongTaskEvent(LongTaskEvent.LONG_TASK_QUESTION_END,progress));
//                }
//            }
//        }));
        try {
            builder.sslSocketFactory(getSSLSocketFactory(context));
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
        return builder.build();
    }
    public ApiFileUploadListService providerApiFileUploadServices(Context context, int i) {
        mApiFileUploadListService = providerApiFileUploadRetrofits(context, i).create(ApiFileUploadListService.class);
        return mApiFileUploadListService;
    }
    Retrofit providerApiFileUploadRetrofits(Context context, int i) {
        mApiFileUploadRetrofit = new Retrofit.Builder().baseUrl(ConfigUtils.getUploadUrl(context)).addConverterFactory(GsonConverterFactory.create()).client(providerFileUploadOkHttpClients(context, i)).build();
        return mApiFileUploadRetrofit;
    }
    OkHttpClient providerFileUploadOkHttpClients(Context context, final int i) {
        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.readTimeout(100, TimeUnit.SECONDS);
        builder.writeTimeout(100, TimeUnit.SECONDS);
        builder.connectTimeout(100, TimeUnit.SECONDS);
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(logging);
            builder.addNetworkInterceptor(logging);
        }
        builder.addInterceptor(new FetchCookiesInterceptor(context));
        builder.addInterceptor(new SetCookiesInterceptor(context));
        builder.addInterceptor(new UploadProgressInterceptor(new CountingRequestBody.Listener() {
            @Override
            public void onRequestProgress(long bytesWritten, long contentLength, boolean done) {
//                if(BuildConfig.DEBUG) {
//                    Log.e("aaa" + i, "progress: " + (int) ((100 * bytesWritten) / contentLength) + "..." + (done ? "done" : "uploading"));
                    double progress = (double) ((100 * bytesWritten) / contentLength) * 0.9;
                    EventBusUtil.post(new LongTaskEvent(LongTaskEvent.LONG_TASK_QUESTION_END, progress, i));
//                }
            }
        }));
        try {
            builder.sslSocketFactory(getSSLSocketFactory(context));
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
        return builder.build();
    }
    public ApiWXPayService providerApiWXPayService(Context context) {
        if (mApiWXPayService == null) {
            mApiWXPayService = providerApiWXPayRetrofit(context).create(ApiWXPayService.class);
        }
        return mApiWXPayService;
    }
    Retrofit providerApiWXPayRetrofit(Context context) {
        if (mApiWXPayRetrofit == null) {
            mApiWXPayRetrofit = new Retrofit.Builder()
                    .baseUrl(ConfigUtils.getApiUrl(context))
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(providerFileUploadOkHttpClient())
                    .build();
        }
        return mApiWXPayRetrofit;
    }
    OkHttpClient providerFileUploadOkHttpClient() {
        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.readTimeout(100, TimeUnit.SECONDS);
        builder.writeTimeout(100, TimeUnit.SECONDS);
        builder.connectTimeout(100, TimeUnit.SECONDS);
        if(BuildConfig.DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(logging);
            builder.addNetworkInterceptor(logging);
        }
        //        builder.addInterceptor(new UploadProgressInterceptor(new CountingRequestBody.Listener() {
        //            @Override
        //            public void onRequestProgress(long bytesWritten, long contentLength,boolean done) {
        //                if(BuildConfig.DEBUG) {
        //                    Log.e("aaa", "progress: " + (int) ((100 * bytesWritten) / contentLength) + "..." + (done ? "done" : "uploading"));
        //                    double progress=(double) ((100 * bytesWritten) / contentLength)*0.2+80;
        //                    EventBusUtil.post(new LongTaskEvent(LongTaskEvent.LONG_TASK_QUESTION_END,progress));
        //                }
        //            }
        //        }));
        return builder.build();
    }

}
